#pragma once
#include <vector>

#include <osg/Vec2d>
#include <osg/Vec3d>
#include <osg/Point>

#include <Standard_Handle.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>

#include "INode.h"
#include "OSGNodeMask.h"

//const int NoPickMask = 1;
const int D2CurveMask = 2;
const int D3CurveMask = 4;
const int D3SurfaceMask = 16;
const int D2LineMask = 32;
const int D3LineMask = 64;
const int PlaneMask = 128;

extern float g_alpha;
extern osg::Vec4f g_selectedFaceColor;
extern osg::Vec4f g_faceColor;

void setAlpha(float alpha);

void rotate2D(const double x, const double y, const double angle, osg::Vec3d& point);
osg::Matrixd rotate2DMatrix(const double x, const double y, const double angle);
// 点的二维镜像，z分量被忽略
osg::Vec3d mirror2D(const osg::Vec3d& start, const osg::Vec3d& end, const osg::Vec3d& original);


class JsonReader;
class Geom2d_Curve;
class Geom2d_TrimmedCurve;
class Geom_Curve;
class Geom_TrimmedCurve;
class Ent : public INode, public IStretchable
{
public:
	Ent(INode* parent);
	virtual void copy(const Ent& ent);
	virtual std::shared_ptr<Ent> clone() const;
	virtual void save(QJsonObject &json) const = 0;
	virtual void load(const QJsonObject& json, JsonReader& reader) = 0;
	virtual void move(const osg::Vec3d& offset);
	virtual void scale(const osg::Vec3d& center, double scale);
	std::vector<osg::Vec3d> getAllWCSHandles() const;
	// 夹点, OCS坐标系, 用于捕捉和stretch
	virtual std::vector<osg::Vec3d> handles() const;
	// stretch 第index个夹点，offset是OCS上的位移
	virtual void stretch(int index, const osg::Vec3d &offset);
	virtual bool explode(std::vector<std::shared_ptr<Ent>>& result) const;
	virtual void updateColor();
	// 绕着过XOY平面上basePoint的竖直轴逆时针旋转angle弧度
	virtual void rotate(const double angle, const osg::Vec2d& basePoint);
	LEAF_METHODS;
};

class Ent2D : public Ent
{
public:
	Ent2D(INode* parent);
	virtual void mirror(const osg::Vec3d& start, const osg::Vec3d& end) {};
	virtual void setColor(const osg::Vec4 &color);
};

struct SectionParam
{
	int sectionNo = 0;
	double param = 0;
};
bool getSectionParam(const std::vector<Handle(Geom2d_Curve)>& curves, const gp_Pnt2d & point, SectionParam & result);
void getStartEndParam(const std::vector<Handle(Geom2d_Curve)>& curves, SectionParam & from, SectionParam & to);
bool operator<(const SectionParam & x1, const SectionParam & x2);

class Ent3DCurve;
class Ent2DCurve : public Ent2D
{
public:
	Ent2DCurve(INode* parent);
	virtual std::vector<Handle(Geom2d_Curve)> getCurve2d() const;
	// front - true, 首端; false, 末端.
	virtual std::shared_ptr<Ent2DCurve> extend(bool front, double param, const gp_Pnt2d& point) const;
	// 裁剪掉[from, to]这一段
	virtual std::vector<std::shared_ptr<Ent2DCurve>> trim(const SectionParam& from, const SectionParam& to) const;
	virtual bool offset(double offset);
	virtual bool offset(double offset,const osg::Vec3d& offsetSide);
	virtual std::vector<std::shared_ptr<Ent3DCurve>> to3d();
};

class Ent3D : public Ent
{
public:
	Ent3D(INode* parent);
};

class Ent3DCurve : public Ent3D
{
public:
	Ent3DCurve(INode* parent);
	virtual std::vector<Handle(Geom_Curve)> getCurve3d() const;
	virtual void setColor(const osg::Vec4 &color);
};

class Ent3DFace : public Ent3D
{
public:
	Ent3DFace(INode* parent);
	std::vector<std::vector<osg::Vec3d>> getWCSEdgePoints() const;
	// implemented by surface, polygon
	virtual std::vector<std::vector<osg::Vec3d>> getEdgePoints() const;
	virtual void reverse();
};

std::vector<std::shared_ptr<Ent>> convert(const std::vector<std::shared_ptr<Ent2D>>& con);
std::set<std::shared_ptr<INode>> convertToSet(const std::vector<std::shared_ptr<Ent2D>>& con);

typedef  std::shared_ptr<Ent>(*CreateFunc)(INode* parent);
bool regEntClass(const std::string& className, CreateFunc creator);
std::shared_ptr<Ent> createInstance(const std::string& className, INode* parent);

void regAllEnts();
